﻿/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#ifndef FastBuffer_h__
#define FastBuffer_h__

namespace SkyEngine2d
{
	
	/*!
	 \brief 快速缓存区
	*/
	template<typename T>
	class FastBuffer
	{
	public:
	
		//! 构造一个缓存区
		/*!
		\param int defalut_capacity 默认分配的容量
		*/
		FastBuffer(int defalut_capacity = 128)
			:m_buffer(0)
			, m_capacity(0)
			, m_size(0)
			, m_offset(0)
		{
			this->reserve(defalut_capacity);
		}
	
		//! 拷贝构造
		/*!
		\param const FastBuffer<T> & buffer
		*/
		FastBuffer(const FastBuffer<T>& buffer)
		{
			m_buffer = nullptr;
			m_capacity = buffer.m_capacity;
			m_size = buffer.m_size;
			m_offset = buffer.m_offset;
	
			if (m_size + m_capacity > 0)
			{
				m_buffer = (T*)malloc((m_size + m_capacity) * sizeof(T));
				assert(m_buffer && buffer.m_buffer);
				if (m_size > 0)
					memcpy((char*)m_buffer, (char*)buffer.m_buffer, m_size * sizeof(T));
			}
		}
	
		//! 移动构造
		/*!
		\param FastBuffer<T> & & buffer
		*/
		FastBuffer(FastBuffer<T> && buffer)
		{
			m_buffer = buffer.m_buffer;
			m_capacity = buffer.m_capacity;
			m_size = buffer.m_size;
			m_offset = buffer.m_offset;
	
			buffer.m_offset = 0;
			buffer.m_size = 0;
			buffer.m_buffer = 0;
			buffer.m_capacity = 0;
		}
	
		//! 拷贝赋值
		/*!
		\param const FastBuffer<T> & buffer
		\return FastBuffer<T>&
		*/
		FastBuffer<T>& operator=(const FastBuffer<T> & buffer)
		{
			if (this == &buffer)
			{
				return *this;
			}
	
			free(m_buffer);
			m_buffer = nullptr;
	
			int allocate_size = buffer.m_size + buffer.m_capacity;
			if (allocate_size > 0)
			{
				m_buffer = (T*)malloc(allocate_size * sizeof(T));
				if (buffer.m_size > 0)
				{
					memcpy(m_buffer, buffer.m_buffer, buffer.m_size);
				}
			}
	
			m_offset = buffer.m_offset;
			m_capacity = buffer.m_capacity;
			m_size = buffer.m_size;
	
			return *this;
		}
	
		//! 移动赋值
		/*!
		\param FastBuffer<T> & & buffer
		\return FastBuffer<T>&
		*/
		FastBuffer<T>& operator=(FastBuffer<T> && buffer)
		{
			if (this == &buffer)
			{
				return *this;
			}
	
			free(m_buffer);
	
			m_buffer = buffer.m_buffer;
			m_capacity = buffer.m_capacity;
			m_size = buffer.m_size;
			m_offset = buffer.m_offset;
	
			buffer.m_offset = 0;
			buffer.m_size = 0;
			buffer.m_buffer = 0;
			buffer.m_capacity = 0;
	
			return *this;
		}
	
	
		//! 析构
		~FastBuffer()
		{
			free(m_buffer);
		}
	
		//! 追加数据
		/*!
		\param const T* data 追加的数据块
		\param int size 数据块中数据的数量
		\return void
		*/
		void append(const T * data, int size)
		{
			if (size > m_capacity)
			{
				this->allocate(size);
			}
	
			assert(m_capacity >= size);
	
			int data_size = size * sizeof(T);
			std::memcpy((char*)m_buffer + m_offset, (char*)data, data_size);
			m_offset += data_size;
	
			m_capacity -= size;
			m_size += size;
	
			return;
		}
	
		//! 追加一个数据
		/*!
		\param T & & value 数据
		\return void
		*/
		void append(T && value)
		{
			if (m_capacity < 1)
			{
				this->allocate(1);
			}
	
			m_buffer[m_size] = std::forward<T>(value);
			++m_size;
			--m_capacity;
			m_offset += sizeof(T);
		}
	
		//! 追加一个数据
		/*!
		\param const T & value  数据
		\return void
		*/
		void append(const T & value)
		{
			if (m_capacity < 1)
			{
				this->allocate(1);
			}
	
			m_buffer[m_size] = value;
			++m_size;
			--m_capacity;
			m_offset += sizeof(T);
		}
	
		//! 获取数据的指针
		/*!
		\return const T*
		*/
		const T* getData() const
		{
			return (T*)m_buffer;
		}
	
		//! 获取数据的数量
		/*!
		\return int
		*/
		int getSize() const
		{
			return m_size;
		}
	
		//! 获取容量
		/*!
		\return int
		*/
		int getCapacitry()const
		{
			return m_capacity;
		}
	
		//! 预分配容量
		/*!
		\param int size 预分配的大小
		\return void
		*/
		void reserve(int size)
		{
			if (size > m_capacity)
			{
				auto tmp = m_buffer;
				m_buffer = this->reAllocate(size - m_capacity);
				free(tmp);
			}
			return;
		}
	
		//! 获取数据所占内存的大小  单位 字节
		/*!
		\return int
		*/
		int getMemSize()
		{
			return sizeof(T)* m_size;
		}
	
		//! 取值
		/*!
		\param int index  值的下标
		\return const T&
		*/
		const T& operator[](int index)const
		{
			assert(index < m_size);
			return (m_buffer)[index];
		}
	
		//! 取值
		/*!
		\param int index 值的下标
		\return T&
		*/
		T& operator[](int index)
		{
			assert(index < m_size);
			return m_buffer[index];
		}
	
		//! 清空缓存
		/*!
		\return void
		\note clear 并不会释放内存
		*/
		void clear()
		{
			m_capacity += m_size;
			m_size = 0;
			m_offset = 0;
		}
	
		//! 释放内存
		/*!
		\return void
		*/
		void freeMem()
		{
			this->clear();
			free(m_buffer);
			m_buffer = nullptr;
		}
	
	private:
	
		//! 扩张内存
		/*!
		\param int need_size 现在需要的 容量
		\return void
		*/
		void allocate(int need_size)
		{
			if (need_size > m_capacity)
			{
				this->reAllocate(need_size + m_size + m_capacity);
			}
			return;
		}
	
		//! 追加 size 大小的内存
		/*!
		\param int size 
		\return T*  
		*/
		T* reAllocate(int size)
		{
			int alloc_size = m_size + m_capacity + size;
			T* tmp = (T*)malloc(alloc_size * sizeof(T));
			m_capacity = alloc_size;
	
			if (!m_size)
			{
				return tmp;
			}
	
			assert(m_buffer && tmp);
			std::memcpy((char*)tmp, (char*)m_buffer, m_size * sizeof(T));
	
			m_capacity -= m_size;
	
			return tmp;
		}
	
	private:
		T* m_buffer;
		int		m_size;
		int		m_capacity;
		int     m_offset;
	};
}



#endif // FastBuffer_h__
